﻿using Mapster;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using RuoVea.Api.Configures;
using RuoVea.ExUtil.Exceptions;
using RuoVea.Entity;
using RuoVea.EventBus;
using RuoVea.ExApp;
using RuoVea.ExDto;
using RuoVea.ExEnum;
using RuoVea.ExFilter;
using RuoVea.Service;
using System.ComponentModel.DataAnnotations;
using UAParser;
using RuoVea.ExUtil.EnumExtension;
using SqlSugar;
using RuoVea.ExIdGen;

namespace RuoVea.Api.Controllers
{
    public class AuthController : ApiBaseController
    {
        private readonly IHttpContextAccessor _httpContextAccessor;
        private readonly IEventPublisher _eventPublisher;
        private readonly IUserManager _userManager; // 用户管理
        private readonly ISysUserService _sysUserService;
        private readonly ISysRoleService _sysRoleService;
        private readonly ISysMenuService _sysMenuService;
        private readonly ISqlSugarClient _sqlSugarClient;
        /// <summary>
        /// 
        /// </summary>
        /// <param name="httpContextAccessor"></param>
        /// <param name="eventPublisher"></param>
        /// <param name="userManager"></param>
        /// <param name="sysRoleService"></param>
        /// <param name="sysMenuService"></param>
        /// <param name="sysUserService"></param>
        public AuthController(IHttpContextAccessor httpContextAccessor, IEventPublisher eventPublisher,

            IUserManager userManager,
            ISysRoleService sysRoleService,
            ISysMenuService sysMenuService,
            ISqlSugarClient sqlSugarClient,
            ISysUserService sysUserService)
        {
            _httpContextAccessor = httpContextAccessor;
            _eventPublisher = eventPublisher; _userManager = userManager;

            _sysUserService = sysUserService;
            _sysRoleService = sysRoleService;
            _sysMenuService = sysMenuService;
            _sqlSugarClient = sqlSugarClient;
        }

        /// <summary>
        /// 用户登录
        /// </summary>
        /// <param name="input"></param>
        /// <remarks>默认用户名/密码：admin/admin</remarks>
        /// <returns></returns>
        [HttpPost("/login")]
        [AllowAnonymous]
        public async Task<string> LoginAsync([Required] LoginInput input)
        {
            // 获取加密后的密码
            var encryptPassword = RuoVea.ExCrypt.Md5Crypt.Encrypt(input.Password);// MD5Encryption.Encrypt("123456");

            // 判断用户名和密码是否正确(排除全局多租户过滤器)Filter(null,true)
            var user = await _sysUserService.LoginAsync(input);
            _ = user ?? throw new ParamiterException(ErrorCode.D1000.GetEnumText());

            // 验证账号是否被冻结
            if (user.Status == StatusEnum.DISABLE)
                throw new ParamiterException(ErrorCode.D1017.GetEnumText());
            // 生成Token令牌
            //var accessToken = await _jwtBearerManager.CreateTokenAdmin(user);
            var accessToken = JWTEncryption.Encrypt(new Dictionary<string, object>
            {
                {ClaimConst.CLAINM_USERID, user.Id},
                {ClaimConst.CLAINM_ACCOUNT, user.Account},
                {ClaimConst.CLAINM_NAME, user.Name},
                {ClaimConst.CLAINM_SUPERADMIN, user.AdminType},
            });

            // 设置Swagger自动登录
            _httpContextAccessor.HttpContext.SigninToSwagger(accessToken);

            // 生成刷新Token令牌
            var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, 30);

            // 设置刷新Token令牌
            _httpContextAccessor.HttpContext.Response.Headers["x-access-token"] = refreshToken;

            var httpContext = App.HttpContext;
            await _eventPublisher.PublishAsync(new ChannelEventSource("Update:UserLoginInfo",
                new SysUser { Id = user.Id, LastLoginIp = httpContext.GetLocalIpAddressToIPv4(), LastLoginTime = DateTime.Now }));
            return accessToken;
        }

        /// <summary>
        /// 获取当前登录用户信息
        /// </summary>
        /// <returns></returns>
        [HttpGet("getLoginUser")]
        public async Task<LoginOutput> GetLoginUserAsync()
        {
            var user = _userManager.User;
            var userId = user.Id;

            var httpContext = App.GetService<IHttpContextAccessor>().HttpContext;
            var loginOutput = user.Adapt<LoginOutput>();

            loginOutput.LastLoginTime = user.LastLoginTime = DateTime.Now;
            var ip = HttpNewUtil.Ip;
            loginOutput.LastLoginIp = user.LastLoginIp =
                string.IsNullOrEmpty(user.LastLoginIp) ? HttpNewUtil.Ip : ip;

            var clent = Parser.GetDefault().Parse(httpContext.Request.Headers["User-Agent"]);
            loginOutput.LastLoginBrowser = clent.UA.Family + clent.UA.Major;
            loginOutput.LastLoginOs = clent.OS.Family + clent.OS.Major;

            // 角色信息
            loginOutput.Roles = await _sysRoleService.GetUserRoleList(userId);

            // 权限信息
            loginOutput.Permissions = await _sysMenuService.GetLoginPermissionList(userId);



            //// 菜单信息
            //if (loginOutput.Apps.Count > 0)
            //{
            //    var defaultActiveAppCode = loginOutput.Apps.FirstOrDefault().Code;
            //    loginOutput.Menus = await _sysMenuService.GetLoginMenusAntDesign(userId, "");
            //    loginOutput.Menus.ForEach(item => { item.Hidden = item.Application != defaultActiveAppCode; });
            //}

            // 增加登录日志
            await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
                new SysLogVis
                {
                    Name = user.Name,
                    Success = YesOrNot.Y,
                    Message = "登录成功",
                    Ip = loginOutput.LastLoginIp,
                    Browser = loginOutput.LastLoginBrowser,
                    Os = loginOutput.LastLoginOs,
                    VisType = LoginType.LOGIN,
                    VisTime = loginOutput.LastLoginTime,
                    Account = user.Name
                }));

            return loginOutput;
        }

        /// <summary>
        /// 退出
        /// </summary>
        /// <returns></returns>
        [HttpGet("logout")]
        [AllowAnonymous]
        public async Task LogoutAsync()
        {
            _httpContextAccessor.HttpContext.SignoutToSwagger();
            var ip = HttpNewUtil.Ip;
            var user = _userManager.User;
            // 增加退出日志
            await _eventPublisher.PublishAsync(new ChannelEventSource("Create:VisLog",
                new SysLogVis
                {
                    Name = user.Name,
                    Success = YesOrNot.Y,
                    Message = "退出成功",
                    VisType = LoginType.LOGOUT,
                    VisTime = DateTime.Now,
                    Account = user.Account,
                    Ip = ip
                }));

            await Task.CompletedTask;
        }

        /// <summary>
        /// 初始化建表建库
        /// </summary>
        /// <returns></returns>
        [HttpGet("CreaterDb")]
        [AllowAnonymous]
        public async Task CreaterDb()
        {
            _sqlSugarClient.CodeFirst.SetStringDefaultLength(200).InitTables(
                  typeof(SysUser),
                  typeof(SysRole),
                  typeof(SysPos),

                  typeof(SysMenu),

                  typeof(SysUserRole),
                  typeof(SysUserPos),
                  typeof(SysRoleMenu),

                  typeof(SysNoticeUser),
                  typeof(SysNotice),

                  typeof(SysLogVis),
                  typeof(SysLogOp),
                  typeof(SysLogEx),

                  typeof(VitaAccount),
                  typeof(VitaUser),
                  typeof(VitaEnchant)
                  );
        }

        /// <summary>
        /// 初始化建表建库
        /// </summary>
        /// <returns></returns>
        [HttpGet("InitData")]
        [AllowAnonymous]
        public async Task InitData()
        {

            List<SysRole> sysRoles = new List<SysRole> {
                new SysRole{ Id=IdGenerator.Id, Code="Ruler",Name="统治者", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,

                new SysRole{ Id=IdGenerator.Id, Code="Five ghost emperors ",Name="五方鬼帝", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,

                new SysRole{ Id=IdGenerator.Id, Code="Ten palace Yama",Name="十殿阎王", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,

                new SysRole{ Id=IdGenerator.Id, Code="Four judges",Name="四大判官", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,

                new SysRole{ Id=IdGenerator.Id, Code="Ghost difference - Ming Shuai",Name="鬼差-冥帅", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,
                new SysRole{ Id=IdGenerator.Id, Code="Ghost difference - Tai Yi",Name="鬼差-泰媪", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,
                new SysRole{ Id=IdGenerator.Id, Code="Ghost messenger",Name="鬼差-勾魂使者", Remark="", DataScopeType= DataScopeType.ALL, Sort=10,Status= StatusEnum.ENABLE } ,
            };
            sysRoles.ForEach(item => { item.Create(); });
            _sqlSugarClient.Insertable(sysRoles).ExecuteCommand();


            List<SysPos> sysPoss = new List<SysPos> {
                new SysPos{ Id=IdGenerator.Id, Code="Netherworld",Name="冥神",Floor="北罗阴酆都山", Remark="地府最高统治者",Sort=10, Status= StatusEnum.ENABLE } ,

                new SysPos{ Id=IdGenerator.Id, Code="Oriental ghost Emperor",Name="东方鬼帝",Floor="桃止山", Remark="治桃止山、鬼门关",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Western ghost Emperor",Name="西方鬼帝",Floor="嶓冢山", Remark="治嶓冢山",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Northern ghost Emperor",Name="北方鬼帝",Floor="罗酆山", Remark="治罗酆山",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Southern ghost Emperor",Name="南方鬼帝",Floor="罗浮山", Remark="治罗浮山",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Central ghost Emperor",Name="中央鬼帝",Floor="抱犊山", Remark="中央鬼帝",Sort=10, Status= StatusEnum.ENABLE } ,


                new SysPos{ Id=IdGenerator.Id, Code=" Qin Guangwang ",Name="秦广王",Floor="第一殿", Remark="专司人间寿夭生死，统管吉凶",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code=" King of Chu River ",Name="楚江王",Floor="第二殿", Remark="专司活大地狱，即寒冰地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code=" Emperor of Song Dynasty ",Name="宋帝王",Floor="第三殿", Remark="专司黑绳大地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Five senses King",Name="五官王",Floor="第四殿", Remark="专司合大地狱，即血池地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="King of hell",Name="阎罗王",Floor="第五殿", Remark="正月初八日诞辰，专司叫唤大地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Bian Chengwang",Name="卞城王",Floor="第六殿", Remark="专司大叫唤大地狱及枉死城",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Taishan King",Name="泰山王",Floor="第七殿", Remark="专司热闹地狱，即肉酱地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="City King",Name="都市王",Floor="第八殿", Remark="专司大热闹大地狱，即闷锅地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Equal King",Name="平等王",Floor="第九殿", Remark="专司铁网阿鼻地狱",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Equal Runner King",Name="转轮王",Floor="第十殿", Remark="专司各殿解到鬼魂，区别善恶，核定等级，发往投生",Sort=10, Status= StatusEnum.ENABLE } ,

                new SysPos{ Id=IdGenerator.Id, Code="Yin Law Department",Name="阴律司 - 崔珏",Floor="未知", Remark="左手执生死薄，右手拿勾魂笔，专门执行为善者添寿，让恶者归阴的任务",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Punish evil Division",Name="罚恶司 - 钟馗",Floor="终南山", Remark="凡来报到的鬼魂，先经孽镜台前映照，显明善恶、区分好坏",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Chacha Division",Name="察查司 - 陆之道",Floor="未知", Remark="让善者得到善报，好事得到弘扬，使恶者受到应得的惩处，并为冤者平反昭雪",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Bounty Department",Name="赏善司 - 魏征",Floor="未知", Remark="生前行善小鬼全部由他安排，根据生前行善程度大小、多少予以奖赏",Sort=10, Status= StatusEnum.ENABLE } ,

                new SysPos{ Id=IdGenerator.Id, Code="Ghost King",Name="鬼王",Floor="暂无", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Meng Po Shen",Name="孟婆神",Floor="暂无", Remark="提供孟婆汤，消除鬼魂的记忆",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Day wandering God",Name="日游神",Floor="暂无", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Night wandering God",Name="夜游神",Floor="暂无", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Black impermanence",Name="黑无常",Floor="暂无", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="White impermanence",Name="白无常",Floor="暂无", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Ox head",Name="牛头",Floor="阎王庙", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Horse face",Name="马面",Floor="阎王庙", Remark="勾魂鬼差",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Leopard tail",Name="豹尾",Floor="暂无", Remark="管理兽类动物亡灵",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="beak",Name="鸟嘴",Floor="暂无", Remark="管理天上鸟类动物亡灵",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="Fish gill",Name="鱼鳃",Floor="暂无", Remark="管理水中鱼类动物亡灵",Sort=10, Status= StatusEnum.ENABLE } ,
                new SysPos{ Id=IdGenerator.Id, Code="wasp",Name="黄蜂",Floor="暂无", Remark="管理地上昆虫动物亡灵",Sort=10, Status= StatusEnum.ENABLE } ,
            };


            List<SysUser> sysUsers = new List<SysUser> {
                new SysUser{ Id=IdGenerator.Id ,Account="superAdmin",Password="4297f44b13955235245b2497399d7a93",NickName="superAdmin",Name="超级管理员",Birthday=DateTime.Now.AddYears(-20),AdminType= AdminType.SuperAdmin,CreatedTime=DateTime.Now,IsDeleted=false,Status= StatusEnum.ENABLE },
                new SysUser{ Id=IdGenerator.Id ,Account="admin",Password="4297f44b13955235245b2497399d7a93",NickName="admin",Name="管理员",Birthday=DateTime.Now.AddYears(-20),CreatedTime=DateTime.Now,IsDeleted=false,Status= StatusEnum.ENABLE },
            };

            sysPoss.ForEach(
                item =>
                {
                    item.Create();  
                    sysUsers.Add(new SysUser { Id = IdGenerator.Id, Account = item.Code.Trim(), Password = "4297f44b13955235245b2497399d7a93", NickName = item.Name.Trim(), Name = item.Name.Trim(), Birthday = DateTime.Parse("0001-09-09"), CreatedTime = DateTime.Now, IsDeleted = false, Status = StatusEnum.ENABLE });

                });
            _sqlSugarClient.Insertable(sysPoss).ExecuteCommand();

            sysUsers.ForEach(item => { item.Create();  });
            _sqlSugarClient.Insertable(sysUsers).ExecuteCommand();


            List<SysUserRole> sysUserRoles = new List<SysUserRole>();
            for (int i = 0; i < sysUsers.Count; i++)
            {
                if (i < 3)
                    sysUserRoles.Add(new SysUserRole { SysUserId = sysUsers[i].Id, SysRoleId = sysRoles[0].Id });

                if (i >= 3 && i < 8)
                    sysUserRoles.Add(new SysUserRole { SysUserId = sysUsers[i].Id, SysRoleId = sysRoles[1].Id });

                if (i >= 8 && i < 19)
                    sysUserRoles.Add(new SysUserRole { SysUserId = sysUsers[i].Id, SysRoleId = sysRoles[2].Id });

                if (i >= 19 && i < 23)
                    sysUserRoles.Add(new SysUserRole { SysUserId = sysUsers[i].Id, SysRoleId = sysRoles[3].Id });

                if (i >= 23 && i < 34)
                    sysUserRoles.Add(new SysUserRole { SysUserId = sysUsers[i].Id, SysRoleId = sysRoles[4].Id });
            }
            _sqlSugarClient.Insertable(sysUserRoles).ExecuteCommand();


            List<SysUserPos> sysUserPoss = new List<SysUserPos>();
            sysUsers.ForEach(item =>
            {
                foreach (var t in sysPoss)
                {
                    if (item.Account == t.Code.Trim())
                        sysUserPoss.Add(new SysUserPos { SysUserId = item.Id, SysPosId = t.Id });
                }
            });
            _sqlSugarClient.Insertable(sysUserPoss).ExecuteCommand();
        }
    }
}
